package org.yiqixue.accounts.service.impl;

import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.yiqixue.accounts.dto.TransactionDTO;
import org.yiqixue.accounts.entity.Account;
import org.yiqixue.accounts.entity.Transaction;
import org.yiqixue.accounts.entity.TransactionStatus;
import org.yiqixue.accounts.entity.TransactionType;
import org.yiqixue.accounts.repository.AccountRepository;
import org.yiqixue.accounts.repository.TransactionRepository;
import org.yiqixue.accounts.service.TransactionService;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 交易服务实现类
 */
@Service
@RequiredArgsConstructor
public class TransactionServiceImpl implements TransactionService {

    private final TransactionRepository transactionRepository;
    private final AccountRepository accountRepository;

    /**
     * 创建新交易
     * @param transactionDTO 交易信息
     * @return 创建的交易信息
     */
    @Override
    @Transactional
    public TransactionDTO createTransaction(TransactionDTO transactionDTO) {
        // 查找账户
        Account account = accountRepository.findByAccountNumber(transactionDTO.getAccountNumber())
                .orElseThrow(() -> new RuntimeException("Account not found"));

        // 创建交易实体
        Transaction transaction = new Transaction();
        transaction.setAccount(account);
        transaction.setAmount(transactionDTO.getAmount());
        transaction.setDescription(transactionDTO.getDescription());
        transaction.setType(transactionDTO.getType());
        transaction.setStatus(transactionDTO.getStatus());
        transaction.setTransactionDate(LocalDateTime.now());
        
        // 如果交易状态为完成，则更新账户余额
        if (transactionDTO.getStatus() == TransactionStatus.COMPLETED) {
            updateAccountBalance(account, transactionDTO.getType(), transactionDTO.getAmount());
        }

        // 保存交易
        Transaction savedTransaction = transactionRepository.save(transaction);

        // 转换为DTO并返回
        return convertToDTO(savedTransaction);
    }

    /**
     * 根据交易类型更新账户余额
     * @param account 账户
     * @param type 交易类型
     * @param amount 交易金额
     */
    private void updateAccountBalance(Account account, TransactionType type, BigDecimal amount) {
        switch (type) {
            case DEPOSIT:
                // 存款增加余额
                account.setBalance(account.getBalance().add(amount));
                break;
            case WITHDRAWAL:
            case PAYMENT:
                // 取款和付款减少余额
                if (account.getBalance().compareTo(amount) < 0) {
                    throw new RuntimeException("Insufficient funds");
                }
                account.setBalance(account.getBalance().subtract(amount));
                break;
            case TRANSFER:
                // 转账暂不处理，需要两个账户之间的交易
                // 这里简化处理为减少当前账户余额
                if (account.getBalance().compareTo(amount) < 0) {
                    throw new RuntimeException("Insufficient funds");
                }
                account.setBalance(account.getBalance().subtract(amount));
                break;
        }
        // 保存更新后的账户
        accountRepository.save(account);
    }

    /**
     * 查询指定手机号的当日特定类型交易
     * @param phoneNumber 手机号
     * @param type 交易类型
     * @return 交易列表
     */
    @Override
    public List<TransactionDTO> findTodayTransactions(String phoneNumber, TransactionType type) {
        LocalDateTime startOfDay = LocalDate.now().atStartOfDay();
        LocalDateTime endOfDay = LocalDate.now().atTime(LocalTime.MAX);

        return transactionRepository.findByPhoneNumberAndTypeAndDate(phoneNumber, type, startOfDay, endOfDay)
                .stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
    }

    /**
     * 将Transaction实体转换为DTO
     * @param transaction 交易实体
     * @return 交易DTO
     */
    private TransactionDTO convertToDTO(Transaction transaction) {
        TransactionDTO dto = new TransactionDTO();
        dto.setTransactionId(transaction.getTransactionId());
        dto.setAccountNumber(transaction.getAccount().getAccountNumber());
        dto.setAmount(transaction.getAmount());
        dto.setTransactionDate(transaction.getTransactionDate());
        dto.setDescription(transaction.getDescription());
        dto.setStatus(transaction.getStatus());
        dto.setType(transaction.getType());
        return dto;
    }
} 